import { bind, Event, extendClassProps, JsonValue, PartialWithUndefinedReactivePropsToNativeProps, react, reactArrayWithUndefined, ReactivePropsToNativePropsAndChanged, reactJsonWithUndefined, SceneObjectKey, track } from "xbsj-base";
import { ESRtsFeatureEditing } from "../ESRtsFeatureEditing";
import { ES3DTileset } from "../ES3DTileset";
import { _getport } from "./types";
import { SceneObjectPickedInfo } from "../../../ESJTypes"
import { ESSceneObject } from "@sdkSrc/ESObjects/base";

export class ESMsTileset extends ES3DTileset {
    static override readonly type = this.register('ESMsTileset', this, { chsName: 'Modelser实时3DTileset图层', tags: ['ESObjects', '_ES_Impl_Cesium', '_ES_Impl_UE'], description: "实时3DTileset图层" });
    override get typeName() { return 'ESMsTileset'; }
    override get defaultProps() { return ESMsTileset.createDefaultProps(); }
    override get json() { return this._innerGetJson() as JsonType; }
    override set json(value: JsonType) { this._innerSetJson(value); }

    public override combinationClass: boolean = true;
    public override getMainClass(): ESSceneObject { return this._es3DTileset; }

    private _es3DTileset = this.dv(new ES3DTileset(`${this.id}_ES3DTileset`));
    get es3DTileset() { return this._es3DTileset; }

    // 数据地址端口号
    private _tilesetServePort = this.dv(react<string>(""));
    get tilesetServePort() { return this._tilesetServePort.value; }
    get tilesetServePortChanged() { return this._tilesetServePort.changed; }
    set tilesetServePort(value: string) { this._tilesetServePort.value = value; }

    async getport() {
        const port = await _getport(this.url as string);
        if (port) {
            this.tilesetServePort = port;
            return port;
        } else {
            throw new Error('服务地址port获取失败!');
        }
    }

    async refresh() {
        if (!this.url || typeof this.url !== 'string') return;
        const u1 = this.url.match(/\/ts\/info\/(.*)/)?.[1]
        const time = +new Date();
        if (u1) {
            const ip = this.tileServiceIp;//http://localhost
            const port = await this.getport();//9014
            this._es3DTileset.url = `${ip}:${port}/tiles/tileset.json` + `?t=${time}`;
        }
        console.log('3dtileset url:', this._es3DTileset.url);
    }

    /**
     * 获取当前服务的ip和port http://localhost:9009/tileservice/service/info/sv1
     * 从this.url中获取http://localhost:9009 ,作为请求地址
     */
    get baseUrl() {
        if (this.url && typeof this.url === 'string') {
            const uri = this.url.match(/^(https?:\/\/[^\/]+)/)?.[1];
            if (!uri) {
                throw new Error('服务地址不合法,baseUrl is not found! 示例: http://localhost:9009/ts/info/ms01');
            }
            return uri;
        } else {
            throw new Error('服务地址不合法,baseUrl is not found! 示例: http://localhost:9009/ts/info/ms01');
        }
    }

    /**
   * 获取当前服务的ip http://localhost:9009/ts/info/ms01
   * 从this.url中获取http://localhost
   */
    get tileServiceIp() {
        if (this.url && typeof this.url === 'string') {
            const ip = this.url.match(/^(https?:\/\/[^:]+)/)?.[1];
            if (!ip) {
                throw new Error('服务地址不合法,ip is not found! 示例: http://localhost:9009/ts/info/ms01');
            }
            return ip
        } else {
            throw new Error('服务地址不合法,ip is not found! 示例: http://localhost:9009/ts/info/ms01');
        }
    }

    /**
     * 图层服务名称 http://localhost:9009/tileservice/service/info/sv1
     * 从this.url中获取sv1
     */
    get tileServiceName() {
        if (this.url && typeof this.url === 'string') {
            const u1 = this.url.match(/\/ts\/info\/(.*)/)?.[1]
            if (!u1) {
                console.log(this.url);
                throw new Error('服务地址不合法,tileServiceName is not found! 示例: http://localhost:9009/ts/info/ms01,');

            }
            return u1
        } else {
            throw new Error('服务地址不合法,tileServiceName is not found! 示例: http://localhost:9009/ts/info/ms01');
        }
    }

    constructor(id?: SceneObjectKey) {
        super(id);

        {
            const loadTileset = async () => {
                if (typeof this.url !== 'string') {
                    console.error('服务地址不合法, Init Error! 示例: http://localhost:9009/ts/info/ms01');
                    return;
                }
                if (!this.url) {
                    this._es3DTileset.url = ""
                } else {
                    this.refresh();
                }
            }
            // loadTileset();
            this.d(this.urlChanged.don(() => { loadTileset() }));
        }

        //属性同步
        {
            this.d(this.components.disposableAdd(this._es3DTileset));
            const tileset = this._es3DTileset;
            this.d(track([tileset, 'allowPicking'], [this, 'allowPicking']));
            this.d(track([tileset, 'collision'], [this, 'collision']));
            this.d(bind([tileset, 'flyToParam'], [this, 'flyToParam']));
            this.d(bind([tileset, 'flyToParam'], [this, 'flyToParam']));
            this.d(bind([tileset, 'editing'], [this, 'editing']));
            // this.d(bind([tileset, 'rotationEditing'], [this, 'rotationEditing']));

            //此处url为服务地址，由服务端返回
            // this.d(track([tileset, 'url'], [this, 'url']));
            this.d(track([tileset, 'actorTag'], [this, 'actorTag']));
            this.d(track([tileset, 'materialMode'], [this, 'materialMode']));
            this.d(track([tileset, 'highlight'], [this, 'highlight']));
            this.d(track([tileset, 'maximumScreenSpaceError'], [this, 'maximumScreenSpaceError']));
            this.d(track([tileset, 'highlightID'], [this, 'highlightID']));
            this.d(track([tileset, 'highlightColor'], [this, 'highlightColor']));

            this.d(bind([tileset, 'offset'], [this, 'offset']));
            this.d(bind([tileset, 'rotation'], [this, 'rotation']));

            this.d(track([tileset, 'czmImageBasedLightingFactor'], [this, 'czmImageBasedLightingFactor']));
            this.d(track([tileset, 'czmLuminanceAtZenith'], [this, 'czmLuminanceAtZenith']));
            this.d(track([tileset, 'czmMaximumMemoryUsage'], [this, 'czmMaximumMemoryUsage']));
            this.d(track([tileset, 'czmClassificationType'], [this, 'czmClassificationType']));
            this.d(track([tileset, 'czmStyleJson'], [this, 'czmStyleJson']));
            this.d(track([tileset, 'czmBackFaceCulling'], [this, 'czmBackFaceCulling']));
            this.d(track([tileset, 'czmDebugShowBoundingVolume'], [this, 'czmDebugShowBoundingVolume']));
            this.d(track([tileset, 'czmDebugShowContentBoundingVolume'], [this, 'czmDebugShowContentBoundingVolume']));
            this.d(track([tileset, 'czmSkipLevelOfDetail'], [this, 'czmSkipLevelOfDetail']));

            this.d(track([tileset, 'colorBlendMode'], [this, 'colorBlendMode']));
            this.d(track([tileset, 'cacheBytes'], [this, 'cacheBytes']));

            this.d(track([tileset, 'clippingPlaneEnabled'], [this, 'clippingPlaneEnabled']));
            this.d(track([tileset, 'unionClippingRegions'], [this, 'unionClippingRegions']));
            this.d(track([tileset, 'clippingPlaneEdgeColor'], [this, 'clippingPlaneEdgeColor']));
            this.d(track([tileset, 'clippingPlaneEdgeWidth'], [this, 'clippingPlaneEdgeWidth']));
            this.d(track([tileset, 'materialParams'], [this, 'materialParams']));

            this.d(bind([tileset, 'supportEdit'], [this, 'supportEdit']));
            this.d(bind([tileset, 'clippingPlanesId'], [this, 'clippingPlanesId']));
            this.d(bind([tileset, 'clippingPlaneIds'], [this, 'clippingPlaneIds']));
            this.d(bind([tileset, 'flattenedPlaneId'], [this, 'flattenedPlaneId']));
            this.d(bind([tileset, 'flattenedPlaneEnabled'], [this, 'flattenedPlaneEnabled']));
            this.d(bind([tileset, 'clippingPlaneId'], [this, 'clippingPlaneId']));
            this.d(bind([tileset, 'excavateId'], [this, 'excavateId']));
        }
        //函数同步
        {
            const es3DTileset = this._es3DTileset;
            this.d(this.refreshTilesetEvent.don(() => { es3DTileset.refreshTileset(); }));
            this.d(this.highlightFeatureEvent.don((...arg) => { es3DTileset.highlightFeature(...arg); }));
            this.d(this.highlightFeatureAndFlyToEvent.don((...arg) => { es3DTileset.highlightFeatureAndFlyTo(...arg); }));
            this.d(this.setFeatureColorEvent.don((...arg) => { es3DTileset.setFeatureColor(...arg); }));
            this.d(this.setFeatureVisableEvent.don((...arg) => { es3DTileset.setFeatureVisable(...arg); }));
            this.d(this.resetFeatureStyleEvent.don((...arg) => { es3DTileset.resetFeatureStyle(...arg); }));
            this.d(this.flyInEvent.don((...arg) => { es3DTileset.flyIn(arg[0]); }));
            this.d(this.flyToEvent.don((...arg) => { es3DTileset.flyTo(arg[0]); }));
            this.d(this.calcFlyToParamEvent.don((...arg) => { es3DTileset.calcFlyToParam(...arg); }));
            this.d(this.calcFlyInParamEvent.don((...arg) => { es3DTileset.calcFlyInParam(...arg); }));
        }
        //事件同步
        {
            const es3DTileset = this._es3DTileset;
            this.d(es3DTileset.tilesetReady.don((tileset) => { this.tilesetReady.emit(tileset); }));

            this.d(es3DTileset.pickedEvent.don((pickedInfo) => {
                // @ts-ignore
                this.pickedEvent.emit(new SceneObjectPickedInfo(this, pickedInfo.childPickedInfo));
            }));
        }
        //显隐控制
        {
            const updateShow = () => {
                this.es3DTileset.show = this.show;
            }
            updateShow();
            this.d(this.showChanged.don(() => { updateShow() }));
        }

    }

    static override defaults = {
        ...ES3DTileset.defaults,
        layerConfig: {} as JsonType
    }

    override getProperties(language?: string) {
        return [
            ...super.getProperties(language),
        ]
    }
}



export namespace ESMsTileset {
    export const createDefaultProps = () => ({
        ...ES3DTileset.createDefaultProps(),
    });
}
extendClassProps(ESMsTileset.prototype, ESMsTileset.createDefaultProps);
export interface ESMsTileset extends ReactivePropsToNativePropsAndChanged<ReturnType<typeof ESMsTileset.createDefaultProps>> { }
type JsonType = PartialWithUndefinedReactivePropsToNativeProps<ReturnType<typeof ESMsTileset.createDefaultProps> & { type: string }>;





